package com.unittec.zk.sdk.root.domain;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.unittec.zk.sdk.root.enums.BizCode;
import com.unittec.zk.sdk.root.enums.BizCodeEnum;
import com.unittec.zk.sdk.root.enums.GatewayCode;
import com.unittec.zk.sdk.root.internal.exception.BusinessException;
import com.unittec.zk.sdk.root.mapping.ApiRequest;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * Created by JiKun.Li on 2017-11-03. Email: tracenet@126.com
 */
@Data
@ApiRequest("网关返回结果")
public class Result<T> {

    @ApiModelProperty("网关响应唯一编号")
    private String resultId;

    @ApiModelProperty(value = "网关返回码", required = true, example = "200", notes = "网关是否处理成功的标识200为成功")
    @JSONField(serializeUsing = GatewayCodeSerialize.class, deserializeUsing = GatewayCodeSerialize.class)
    private GatewayCode code;

    @ApiModelProperty(value = "网关返回码描述", required = true, example = "请求成功", notes = "网关返回码描述")
    private String msg;

    @ApiModelProperty(value = "业务返回码，参见具体的API接口文档", required = true, example = "SUCCESS")
    private String bizCode;

    @ApiModelProperty(value = "业务返回码描述，参见具体的API接口文档", required = true, example = "业务处理成功")
    private String bizMsg;

    @ApiModelProperty("业务返回数据")
    private T data;

    @ApiModelProperty("业务返回数据条数")
    private Long dataTotal;

    @ApiModelProperty(value = "请求编号，用于研发调试")
    private String z1;

    @ApiModelProperty(value = "请求内容，用于研发调试")
    private String z2;

    @JSONField(serialize = false)
    @JsonIgnore
    public boolean isSuccess() {
        return this.code.getCode() == Integer.parseInt(BizCode.SUCCESS.getCode())
            && BizCode.SUCCESS.getCode().equals(this.bizCode);
    }

    private Result() {}

    public static <T> Result<T> success(GatewayRequest request) {
        return build(request, null, 0L, GatewayCode.SUCCESS, BizCode.SUCCESS.getCode(), BizCode.SUCCESS.getMessage());
    }

    public static <T> Result<T> success(GatewayRequest request, T data) {
        return build(request, data, 0L, GatewayCode.SUCCESS, BizCode.SUCCESS.getCode(), BizCode.SUCCESS.getMessage());
    }

    public static <T> Result<T> success(GatewayRequest request, T data, Long dataTotal) {
        return build(request, data, dataTotal, GatewayCode.SUCCESS, BizCode.SUCCESS.getCode(),
            BizCode.SUCCESS.getMessage());
    }

    public static <T> Result<T> error(GatewayRequest request, BizCodeEnum bizCodeEnum, String msg) {
        String message = !StringUtils.isBlank(msg) ? bizCodeEnum.getMessage() + "," + msg : bizCodeEnum.getMessage();
        return build(request, null, 0L, GatewayCode.SUCCESS, bizCodeEnum.getCode(), message);
    }

    public static <T> Result<T> error(GatewayRequest request, BizCodeEnum bizCodeEnum) {
        return build(request, null, 0L, GatewayCode.SUCCESS, bizCodeEnum.getCode(), bizCodeEnum.getMessage());
    }

    public static <T> Result<T> error(GatewayRequest request, T data, BizCodeEnum bizCodeEnum) {
        return build(request, data, 0L, GatewayCode.SUCCESS, bizCodeEnum.getCode(), bizCodeEnum.getMessage());
    }

    public static <T> Result<T> error(GatewayRequest request, T data, String bizCode, String bizMsg) {
        return build(request, data, 0L, GatewayCode.SUCCESS, bizCode, bizMsg);
    }

    public static <T> Result<T> error(GatewayRequest request, String bizCode, String bizMsg) {
        return build(request, null, 0L, GatewayCode.SUCCESS, bizCode, bizMsg);
    }

    /**
     * 2019年7月12日14:21:36 添加 专门返回 try catch 的错误
     *
     * @param request
     * @param msg
     * @param <T>
     * @return
     */
    public static <T> Result<T> error(GatewayRequest request, String msg) {
        String message =
            !StringUtils.isBlank(msg) ? BizCode.ERROR.getMessage() + "," + msg : BizCode.ERROR.getMessage();
        return build(request, null, 0L, GatewayCode.SUCCESS, BizCode.ERROR.getCode(), message);
    }

    public static <T> Result<T> getewayError(GatewayRequest request, BizCodeEnum bizCodeEnum, String msg) {
        String message = !StringUtils.isBlank(msg) ? bizCodeEnum.getMessage() + "," + msg : bizCodeEnum.getMessage();
        return build(request, null, 0L, GatewayCode.ERROR, bizCodeEnum.getCode(), message);
    }

    public static <T> Result<T> getewayError(GatewayRequest request, BizCodeEnum bizCodeEnum, Integer statusCode,
        String msg) {
        String message = !StringUtils.isBlank(msg) ? bizCodeEnum.getMessage() + "," + msg : bizCodeEnum.getMessage();
        return build(request, null, 0L,
            statusCode == null ? GatewayCode.ERROR
                : (GatewayCode.convert(statusCode) == null ? GatewayCode.ERROR : GatewayCode.convert(statusCode)),
            statusCode == null ? bizCodeEnum.getCode() : statusCode + "", message);
    }

    public static BusinessException exception(String message) {
        return new BusinessException(message);
    }

    /**
     * 统一汇总返回
     *
     * @param request
     * @param data
     * @param dataTotal
     * @param code
     * @param bizCode
     * @param bizMsg
     * @param <T>
     * @return
     */
    private static <T> Result<T> build(GatewayRequest request, T data, Long dataTotal, GatewayCode code, String bizCode,
        String bizMsg) {
        Result<T> resultInfo = new Result<T>();
        resultInfo.data = data;
        resultInfo.code = code;
        resultInfo.msg = code.getMessage();
        resultInfo.dataTotal = dataTotal;
        resultInfo.bizMsg = bizMsg;
        resultInfo.bizCode = bizCode;
        if (null != request && null != request.getDebug() && request.getDebug()) {
            resultInfo.setResultId(request.getRequestId());
            resultInfo.setZ1(request.getMethod());
            resultInfo.setZ2(JSON.toJSONString(request.getContent()));
        }
        return resultInfo;
    }

}
